// AbstractType.cpp : implementation file
//

#include "stdafx.h"
#include "AbstractType.h"

Token::pointer AbstractType::normalized() const{
	Token::pointer NewBody = getBody().normalized();  
	Token::pointer Res = new AbstractType(_TYPE(*NewBody),getVar());
	delete NewBody;
	return Res;
}
Token::pointer AbstractType::applyArgument(Token::const_reference To) const{
	if(To.isType())
		return getBody().replaceAll(getVar(), To);	
	throw Type::exception("Illegal Type combination at Token::pointer AbstractType::applyArgument(Token::const_reference To) const");
}

Token::pointer AbstractType::clone() const{
	  return new  AbstractType(*this);
}

string AbstractType::view() const {
		return	string("(!-!")+getVar().view()+
					"."+getBody().view()+
					")";
		};
bool AbstractType::operator==(Token::const_reference To) const {
	if(To.isType()){
			Type::const_reference Ty = _TYPE(To);
			if(Ty.isAbstractType()){
				const AbstractType& AT =  _ABSTRACTTYPE(Ty);
				AtomicType RandomVar;
				Token::pointer LeftArgument = getBody().replaceAll(getVar(), RandomVar);
				Token::pointer RightArgument = AT.getBody().replaceAll(AT.getVar(), RandomVar);
				bool res=LeftArgument->operator==(*RightArgument);
				delete LeftArgument; 
				delete RightArgument;
				return res;
				}
		}
	return false;
}

Token::pointer AbstractType::replaceAll(Token::const_reference To1, Token::const_reference To2) const{		
	if(this->operator ==(To1))
		return To2.clone();

		Token::pointer NewBody = getBody().replaceAll(To1,To2);
		Token::pointer Res = new AbstractType(_TYPE(*NewBody),getVar());
		delete NewBody;
		return Res;
}

Type::const_reference AbstractType::getBody() const{
	return *(static_cast<Type*>(this->VarBody.second));
}
Type::const_reference AbstractType::getVar() const{
	return *(static_cast<Type*>(this->VarBody.first));
}

AbstractType::AbstractType(const Type& Ty1, const  Type& Ty2, const string& ss):
Type(ss), VarBody(AtomicType(),Ty1){
	AtomicType Var;
	Token::pointer NewTy = Ty1.replaceAll(Ty2, Var);
	this->VarBody = TokenPair(Var, *NewTy);
	delete NewTy;
}

AbstractType::AbstractType(const AbstractType& Ty):
Type(Ty),VarBody(Ty.VarBody){
}


AbstractType::~AbstractType(){
}




// AbstractType member functions
